/**
 * Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.springblade.modules.monitor.controller;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ZipUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.read.builder.ExcelReaderBuilder;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.*;
import lombok.AllArgsConstructor;
import org.apache.commons.codec.Charsets;
import org.springblade.common.tool.DownloadUtil;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.BladeUser;
import org.springblade.core.secure.utils.SecureUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.node.INode;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.monitor.dto.DictKnowleadgeDTO;
import org.springblade.modules.monitor.dto.KnowleadgeDTO;
import org.springblade.modules.monitor.entity.Knowleadge;
import org.springblade.modules.monitor.entity.KnowleadgeAttach;
import org.springblade.modules.monitor.service.IKnowleadgeAttachService;
import org.springblade.modules.monitor.service.IKnowleadgeService;
import org.springblade.modules.monitor.vo.KnowleadgeAttachVO;
import org.springblade.modules.monitor.vo.KnowleadgeVO;
import org.springblade.modules.system.entity.Dict;
import org.springblade.modules.system.entity.Param;
import org.springblade.modules.system.excel.UserExcel;
import org.springblade.modules.system.excel.UserImportListener;
import org.springblade.modules.system.service.IDictService;
import org.springblade.modules.system.service.IParamService;
import org.springblade.modules.system.wrapper.DictWrapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.*;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import static org.springblade.common.cache.CacheNames.DICT_LIST;
import static org.springblade.common.cache.CacheNames.DICT_VALUE;

/**
 * 控制器
 *
 * @author Chill
 */
@RestController
@AllArgsConstructor
@RequestMapping("/blade-monitor/knowleadge")
@Api(value = "知识库", tags = "知识库接口")
public class KnowleadgeController extends BladeController {
	private IDictService dictService;
	@Autowired
	private IKnowleadgeService knowleadgeService;

	@Autowired
	private IKnowleadgeAttachService knowleadgeAttachService;

	@Autowired
	private IParamService paramService;
	/**
	 * 类型
	 */
	@GetMapping("/kind")
	@ApiOperationSupport(order = 2)
	@ApiOperation(value = "知识库类型", notes = "获取所有知识库类型")
	public R<List<INode>> kind() {
		Map<String, Object> dict = new HashMap<>();
		dict.put("code", "knowleadge_type");
		@SuppressWarnings("unchecked")
		List<Dict> list = dictService.list(Condition.getQueryWrapper(dict, Dict.class).lambda().orderByAsc(Dict::getSort));
		return R.data(DictWrapper.build().listNodeVO(list));
	}


	/**
	 * 新增或修改
	 */
	@PostMapping("kind/submit")
	@ApiOperationSupport(order = 4)
	@ApiOperation(value = "知识库类型新增或修改", notes = "传入dict")
	public R kindSubmit(@Valid @RequestBody DictKnowleadgeDTO dictKnowleadge) {
		Dict dict = new Dict();
		dict.setCode("knowleadge_type");
		dict.setParentId(dictKnowleadge.getParentId());
		//全部默认为100
		dict.setDictKey(100);
		dict.setDictValue(dictKnowleadge.getDictValue());
		dict.setSort(10);
		BeanUtils.copyProperties(dictKnowleadge,dict);
		return R.status(dictService.submitKnowLeadgeType(dict));
	}


	/**
	 * 删除
	 */
	@PostMapping("kind/remove")
	@ApiOperationSupport(order = 5)
	@CacheEvict(cacheNames = {DICT_LIST, DICT_VALUE}, allEntries = true)
	@ApiOperation(value = "知识库类型删除", notes = "传入ids")
	public R kindRemove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
		return R.status(dictService.removeByIds(Func.toLongList(ids)));
	}


	/**
	 * 自定义分页
	 */
	@GetMapping("/page")
	@ApiOperationSupport(order = 8)
	@ApiOperation(value = "知识分页", notes = "传入knowleadge")
	@ApiImplicitParams({
		@ApiImplicitParam(name = "kindId", value = "知识种类Id", paramType = "query", dataType = "long"),
		@ApiImplicitParam(name = "createUserName", value = "发表人", paramType = "query", dataType = "string"),
		@ApiImplicitParam(name = "keyword", value = "关键字", paramType = "query", dataType = "string"),
		@ApiImplicitParam(name = "startTime", value = "开始时间", paramType = "query", dataType = "string"),
		@ApiImplicitParam(name = "endTime", value = "结束时间", paramType = "query", dataType = "string")
	})
	public R<IPage<KnowleadgeVO>> page(@ApiIgnore KnowleadgeDTO knowleadge, Query query) {
		IPage<KnowleadgeVO> pages = knowleadgeService.selectKnowleadgePage(Condition.getPage(query), knowleadge);
		return R.data(pages);
	}

	@GetMapping("/detail")
	@ApiOperationSupport(order = 6)
	@ApiOperation(value = "知识详情", notes = "传入knowleadge")
	public R<Knowleadge> detail(Integer id) {
		Knowleadge knowleadge = new Knowleadge();
		knowleadge.setId(id);
		Knowleadge detail = knowleadgeService.getOne(Condition.getQueryWrapper(knowleadge));
		return R.data(detail);
	}

	/**
	 * 新增或修改
	 */
	@PostMapping("/submit")
	@ApiOperationSupport(order = 9)
	@ApiOperation(value = "新增或修改知识", notes = "传入knowleadge")
	public R submit(@Valid @RequestBody Knowleadge knowleadge, HttpServletRequest httpServletRequest) {

		//此时为更新操作
		if (knowleadge.getId() == null) {
			knowleadge.setCreateTime(LocalDateTime.now());
		}
		//获取当前登录人
		BladeUser user = SecureUtil.getUser(httpServletRequest);
		knowleadge.setCreateUser(user.getUserId());
		knowleadge.setUpdateTime(LocalDateTime.now());
		return R.status(knowleadgeService.saveOrUpdate(knowleadge));
	}

	/**
	 * 删除
	 */
	@PostMapping("/remove")
	@ApiOperationSupport(order = 10)
	@ApiOperation(value = "删除知识", notes = "传入ids,以逗号隔开")
	public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
		return R.status(knowleadgeService.removeByIds(Func.toLongList(ids)));
	}


	@GetMapping("/attach")
	@ApiOperationSupport(order = 11)
	@ApiOperation(value = "对应此知识的所有附件", notes = "获取对应此知识的所有附件")
	public R<List<KnowleadgeAttach>> getAttaches(@RequestParam("knowleadgeId") Integer knowleadgeId) {
		List<KnowleadgeAttach> list = knowleadgeService.getAttaches(knowleadgeId);
		return R.data(list);
	}

	/**
	 * 所有图片的
	 */

	/**
	 * 上传附件
	 */
	@PostMapping("/attach/upload")
	@ApiOperationSupport(order = 12)
	@ApiOperation(value = "添加附件", notes = "添加附件（每次仅允许添加一个）")
	public R importUser(MultipartFile file, Integer konwleadgeId,Integer type) {
		String filename = file.getOriginalFilename();
		if (StringUtils.isEmpty(filename)) {
			throw new RuntimeException("请上传文件!");
		}

		//获取 参数配置表中 文件上传路径
		//查询配置的时间间隔
		List<Param> list = paramService.list();
		Optional<Param> first = list.stream().filter(x -> {
			return x.getParamKey().equalsIgnoreCase("system.knowleadge.attachdir");
		}).findFirst();
		String targetRootPath =  first.get().getParamValue();
		String yyyyMMdd = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));

		String targetPath = targetRootPath.endsWith("/")?targetRootPath + yyyyMMdd:targetRootPath+ "/" + yyyyMMdd;

		if(!FileUtil.exist(targetPath)){
			FileUtil.mkdir(targetPath);
		}

		//判断是否存在同名文件
		QueryWrapper<KnowleadgeAttach> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("knowleadge_id", konwleadgeId);
		List<KnowleadgeAttach> attaches = knowleadgeAttachService.getBaseMapper().selectList(queryWrapper);
//		for (KnowleadgeAttach knowleadgeAttach : attaches) {
//			if(knowleadgeAttach.getAttachName().equalsIgnoreCase(filename)){
//				return R.fail("存在同名文件");
//			}
//		}

		//写入到目标
		File fileDestPathAndName = new File(targetPath + "/" + filename);
		try (InputStream inputStream = new BufferedInputStream(file.getInputStream())) {
			//不存在则创建
			FileUtil.writeFromStream(inputStream, fileDestPathAndName);
		} catch (IOException e) {
			e.printStackTrace();
		}

		KnowleadgeAttach knowleadgeAttach = new KnowleadgeAttach();
		knowleadgeAttach.setAttachName(filename);
		knowleadgeAttach.setCreateTime(LocalDateTime.now());
		knowleadgeAttach.setKnowleadgeId(konwleadgeId);
		knowleadgeAttach.setType(type);

		knowleadgeAttach.setPath(targetPath + "/" + filename);
		knowleadgeAttachService.save(knowleadgeAttach);
		return R.success("操作成功");
	}


	@GetMapping("/attach/remove")
	@ApiOperationSupport(order = 12)
	@ApiOperation(value = "删除附件", notes = "传入ids,以逗号隔开")
	public R removeAttaches(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
		return R.data(knowleadgeAttachService.removeByIds(Func.toIntList(ids)));
	}


	@GetMapping("/attach/download")
	@ApiOperationSupport(order = 13)
	@ApiOperation(value = "下载知识对应的附件", notes = "下载知识对应的附件")
	public void downloadAttaches(@RequestParam("knowleadgeId") Integer knowleadgeId, @ApiParam(value = "主键集合", required = true) @RequestParam String ids,
							  HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
		List<KnowleadgeAttach> list = knowleadgeService.getAttaches(knowleadgeId);
		List<KnowleadgeAttach> collect = list.stream().filter(x -> x.getType() == 2).collect(Collectors.toList());

		String fileName = "";
		boolean flag = Func.toIntList(ids).size() > 1;
		String onlyFile = null;
		if(flag){
			//打包成压缩文件
			fileName = "文件集合.zip";
		}else{
			Optional<KnowleadgeAttach> first = collect.stream().filter(x -> x.getId() == Func.toIntList(ids).get(0)).findFirst();
			onlyFile = first.get().getPath();
			fileName = first.get().getAttachName();
		}

		BladeUser user = SecureUtil.getUser(httpServletRequest);
		String tempPath = "/temp/" + user.getUserId() + "/" + fileName;
		try {
			DownloadUtil.setDownloadFileName(URLEncoder.encode(fileName, Charsets.UTF_8.name())
				, httpServletRequest, httpServletResponse);
			OutputStream out = httpServletResponse.getOutputStream();
			List<File> fileList = new ArrayList<>();

			if(flag){
				collect.forEach(x->{
					if(Func.toIntList(ids).contains(x.getId())){
						fileList.add(new File(x.getPath()));
					}

				});
				File[] files = new File[list.size()];

				File file = new File(tempPath);

				ZipUtil.zip(file, false,  fileList.toArray(files));
				try(InputStream inputStream = new FileInputStream(file)) {
					IoUtil.copy(inputStream, out);
				}

			}else{
				try(InputStream inputStream = new FileInputStream(new File(onlyFile))) {
					IoUtil.copy(inputStream, out);
				}
			}
			out.close();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

}
